package com.ukefu.webim.web.handler.api.rest;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.Menu;
import com.ukefu.util.UKTools;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.repository.PbxHostRepository;
import com.ukefu.webim.service.repository.StatusEventRepository;
import com.ukefu.webim.util.HttpClientUtil;
import com.ukefu.webim.util.RestResult;
import com.ukefu.webim.util.RestResultType;
import com.ukefu.webim.web.handler.Handler;
import com.ukefu.webim.web.handler.api.request.SearchData;
import com.ukefu.webim.web.model.PbxHost;
import com.ukefu.webim.web.model.StatusEvent;
import com.ukefu.webim.web.model.SystemConfig;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;

@Controller
@RequestMapping({"/api/callcenter"})
public class ApiCallcenterController
        extends Handler
{
    @Autowired
    private StatusEventRepository statusEventRes;
    @Value("${web.upload-path}")
    private String path;
    @Autowired
    private PbxHostRepository pbxHostRes;

    @RequestMapping({"/search"})
    @Menu(type="callcenter", subtype="callcenter", access=true)
    @ApiOperation("返回通话记录列表，支持分页，分页参数为 p=1&ps=50，默认分页尺寸为 20条每页")
    public ResponseEntity<RestResult> index(ModelMap map , HttpServletRequest request , @Valid final String discaller , @Valid final String discalled
            , @Valid final String begin , @Valid final String end , @Valid final String direction, @Valid final String userid, @Valid final String organ
            , @Valid final String ringdurbegin , @Valid final String ringdurend , @Valid final String incallbegin , @Valid final String incallend
            , @Valid final String record , @Valid final String misscall , @Valid final String calltype, @Valid final String recordbegin, @Valid final String recordend) {
        final String orgi = super.getOrgi(request);
        Page<StatusEvent> page = statusEventRes.findAll(new Specification<StatusEvent>(){
            @Override
            public Predicate toPredicate(Root<StatusEvent> root, CriteriaQuery<?> query,
                                         CriteriaBuilder cb) {
            List<Predicate> list = new ArrayList<Predicate>();
            if(!StringUtils.isBlank(discaller)){
                list.add(cb.equal(root.get("discaller").as(String.class), discaller)) ;
            }
            list.add(cb.equal(root.get("orgi").as(String.class), orgi)) ;
            if(!StringUtils.isBlank(discalled)){
                list.add(cb.equal(root.get("discalled").as(String.class), discalled)) ;
            }
            if(!StringUtils.isBlank(direction)){
                list.add(cb.equal(root.get("direction").as(String.class), direction)) ;
            }
            if(!StringUtils.isBlank(userid)){
                list.add(cb.equal(root.get("userid").as(String.class), userid)) ;
            }
            if(!StringUtils.isBlank(organ)){
                list.add(cb.equal(root.get("organ").as(String.class), organ)) ;
            }
            try {
                if(!StringUtils.isBlank(begin) && begin.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
                    list.add(cb.greaterThan(root.get("createtime").as(Date.class), UKTools.dateFormate.parse(begin))) ;
                }
                if(!StringUtils.isBlank(end) && end.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
                    list.add(cb.lessThan(root.get("createtime").as(Date.class), UKTools.dateFormate.parse(end))) ;
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }

            //振铃时长
            if(!StringUtils.isBlank(ringdurbegin)){
                list.add(cb.greaterThan(root.get("ringduration").as(int.class), Integer.parseInt(ringdurbegin)*1000)) ;
            }
            if(!StringUtils.isBlank(ringdurend)){
                list.add(cb.lessThan(root.get("ringduration").as(int.class), Integer.parseInt(ringdurend)*1000)) ;
            }

            //通话时长
            if(!StringUtils.isBlank(incallbegin)){
                list.add(cb.greaterThan(root.get("duration").as(int.class), Integer.parseInt(incallbegin)*1000)) ;
            }
            if(!StringUtils.isBlank(incallend)){
                list.add(cb.lessThan(root.get("duration").as(int.class), Integer.parseInt(incallend)*1000)) ;
            }

            //录音时长
            if(!StringUtils.isBlank(recordbegin)){
                list.add(cb.greaterThan(root.get("recordtime").as(int.class), Integer.parseInt(recordbegin)*1000)) ;
            }
            if(!StringUtils.isBlank(recordend)){
                list.add(cb.lessThan(root.get("recordtime").as(int.class), Integer.parseInt(recordend)*1000)) ;
            }

            //是否录音
            if(!StringUtils.isBlank(record)){
                list.add(cb.equal(root.get("record").as(boolean.class), record)) ;
            }

            //是否漏话
            if(!StringUtils.isBlank(misscall)){
                list.add(cb.equal(root.get("misscall").as(boolean.class), misscall)) ;
            }

            //呼叫方向
            if(!StringUtils.isBlank(calltype)){
                list.add(cb.equal(root.get("calltype").as(String.class), calltype)) ;
            }


            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        }}, new PageRequest(super.getP(request), super.getPs(request) , Sort.Direction.DESC, "starttime")) ;
        if ((page != null) && (page.getContent() != null) && (page.getContent().size() > 0)) {
            for (StatusEvent statusEvent : page.getContent())
            {
                statusEvent.setTracesip(null);
                statusEvent.setAnswersip(null);
                statusEvent.setHangupsip(null);
            }
        }
        return new ResponseEntity(new RestResult(RestResultType.OK, new SearchData(page)), HttpStatus.OK);
    }

    @RequestMapping({"/voice"})
    @Menu(type="callcenter", subtype="voice", access=true)
    public void play(ModelMap map, HttpServletRequest request, HttpServletResponse response, @Valid String id)
            throws IOException
    {
        StatusEvent statusEvent = statusEventRes.findByIdAndOrgi(id ,super.getOrgi(request)) ;
        if(statusEvent!=null && !StringUtils.isBlank(statusEvent.getHostid())){
            PbxHost pbxHost = null;		//根据 PbxHost配置的 方式获取 录音文件的读取方式
            if(super.isEnabletneant()){
                pbxHost = pbxHostRes.findById(statusEvent.getHostid());
            }else{
                pbxHost = pbxHostRes.findByIdAndOrgi(statusEvent.getHostid(), statusEvent.getOrgi()) ;
            }
            if(pbxHost != null && !StringUtils.isBlank(pbxHost.getRecordpath()) && pbxHost.getRecordpath() != "" && StringUtils.isNotBlank(statusEvent.getRecordfile())){
                String fileName = statusEvent.getRecordfile() ;
                if(statusEvent.getRecordfile().lastIndexOf("/") >= 0) {
                    fileName = statusEvent.getRecordfile().substring(statusEvent.getRecordfile().lastIndexOf("/"), statusEvent.getRecordfile().length()) ;
                }else {
                    fileName = "/"+fileName ;
                }
                response.sendRedirect(pbxHost.getRecordpath()+fileName);
            }else{
                if(statusEvent.getRecordfile() != null) {
                    //在远程oss
                    if("1".equals(statusEvent.getOssstatus())){
                        SystemConfig systemConfig = (SystemConfig) CacheHelper.getSystemCacheBean().getCacheObject("systemConfig", UKDataContext.SYSTEM_ORGI) ;
                        if(systemConfig != null && StringUtils.isNotBlank(systemConfig.getAppid())) {
                            String appId = systemConfig.getAppid();
                            Map<String,Object> paramsMap = new HashMap<>();
                            paramsMap.put("appId",appId);
                            paramsMap.put("objectName",statusEvent.getRecordfilename());
                            String res = HttpClientUtil.doPost(systemConfig.getCloudservergetossobjecturl(),paramsMap);

                            if(StringUtils.isNotBlank(res)){
                                Map<String,Object> resultMap = UKTools.toObject(res,HashMap.class);
                                if(resultMap != null){
                                    Boolean success = (Boolean)resultMap.get("success");
                                    String url = (String)resultMap.get("resultObj");
                                    if(success != null && success && StringUtils.isNotBlank(url)){
                                        response.sendRedirect(url);
                                    }
                                }
                            }
                        }
                    }else{
                        File voiceFile = new File(statusEvent.getRecordfile()) ;
                        if(voiceFile != null && voiceFile.exists() && pbxHost!=null){
                            response.setContentType("audio/wav");
                            response.setContentLength((int) voiceFile.length());
                            FileInputStream input = new FileInputStream(voiceFile) ;
                            try{
                                byte[] data = new byte[1024];
                                int len = 0;
                                while((len = input.read(data) )> 0){
                                    response.getOutputStream().write(data , 0 , len);
                                }
                            }finally{
                                input.close();
                            }
                        }else {
                            response.setContentType("text/html");
                            String record = statusEvent.getRecordfile() ;
                            response.getOutputStream().write(record.getBytes());
                        }
                    }
                }else {
                    response.setContentType("text/html");
                    response.getOutputStream().write(statusEvent.getHostid().getBytes());
                }
            }
        }
    }
}
